本指南分享了提高GPT的效果的策略和方法。这里描述的方法有时可以结合使用以获得更好的效果。同时鼓励多尝试试验,找到最适合自己的方法。

[TOC]

以下是提高Prompt效果的六个策略:

1. 编写清晰的提示

如果GPT输出的内容过长,可以要求进行简短的回复;如果输出过于简单,可以要求使用专业的写作水准输出内容。如果你不喜欢输出的格式,可以提供自己想要的格式。越是明确表达自己的需求,越有可能得到满意的答案。

具体方法:

  • 在查询中提供更多细节可以获得更相关的答案
  • 可以要求模型采用特定的人设
  • 使用分隔符清楚地指示输入的不同部分
  • 指定完成任务所需的步骤
  • 提供例子
  • 指定所需的输出长度

1.1 在查询中包含详细信息以获得更相关的答案

为了获得高度相关的响应,请确保请求中提供了所有重要的详细信息或上下文。否则,模型将会猜测你的意思,结果的相关度也会降低。

在下面的表格中,右边是推荐的写法,效果会比左边的更好,因为提供了更多具体的细节信息。

更差的 更好的
如何在 Excel 中添加数字? 如何在 Excel 中添加一行美元金额?我想对整张行自动执行此操作,所有总计都在右侧名为“总计”的列中结束。
谁是总统? 谁是 2021 年墨西哥总统?选举频率如何?
编写代码来计算斐波那契数列。 编写一个 TypeScript 函数来高效计算斐波那契数列。自由地注释代码以解释每部分的作用以及为什么这样编写。
总结会议记录。 用一个段落总结会议记录。然后写下演讲者的 Markdown 列表以及他们的每个要点。最后,列出发言人建议的后续步骤或行动项目(如果有)。

1.2 要求模型采用特定的角色

GPT的系统消息(system)可用于指定模型在其回复中使用的角色(GPT扮演的角色或行为表现的描述)。

GPT角色 角色内容
SYSTEM 当我请求帮助写一些东西时,你会回复一份文档,其中每个段落至少包含一个笑话或有趣的评论。
USER 给我的钢螺栓供应商写一封感谢信,感谢他们在短时间内准时交货。这使我们能够交付一份重要的订单。

没有系统角色的回复效果:

提供了系统角色的回复效果:

很明显,指定了系统角色信息之后,回复的内容的确是更有趣了。

熟悉Prompt的同学们应该都知道,通常在写Prompt的时候要先设定角色:“你是XX方面的专家”,这并非玄学,而是有科学根据的。

GPT在训练的时候,有各种训练数据,有的质量高有的质量低,而默认情况下,生成高质量数据和低质量数据的概率差不多,但是当你给它设定XX专家的角色时,它会尽可能把概率分布在高质量的解决方案上。

以下是Andrej Karpathy在State of GPT中的一段演讲的文字内容:

下面我要讲的这点对LLM的理解非常有趣,我觉得这算是LLM的一种心理特性:LLM并不追求成功,而是追求模仿。你希望它成功,那就需要向它明确要求。这里的意思是,在训练Transformer的过程中,它们有各种训练集,而这些训练数据中可能涵盖了各种不同质量的表现。比如,可能有一个关于物理问题的提示,然后可能有学生的解答完全错误,但也可能有专家的答案完全正确。尽管Transformer可以识别出低质量的解决方案和高质量的解决方案,但默认情况下,它们只会模仿所有的数据,因为它们仅仅是基于语言模型进行训练的。

在实际测试中,你其实需要明确要求它表现得好。在这篇论文的实验中,他们尝试了各种提示。例如,“让我们逐步思考”这种提示就很有效,因为它把推理过程分散到了许多记号上。但效果更好的是这样的提示:“让我们以一步一步的方式解决问题,以确保我们得到正确的答案。” 这就好像是在引导Transformer去得出正确的答案,这会使Transformer的表现更好,因为此时Transformer不再需要把它的概率质量分散到低质量的解决方案上,尽管这听起来很荒谬。

基本上,你可以自由地要求一个高质量的解决方案。比如,你可以告诉它,“你是这个话题的领先专家。假装你的智商是120。” 但不要尝试要求太高的智商,因为如果你要求智商400,可能就超出了数据分布的范围,更糟糕的是,你可能落入了类似科幻内容的数据分布,它可能会开始展现一些科幻的,或者说角色扮演类的东西。所以,你需要找到适合的智商要求。我想这可能是一个U型曲线的关系。

1.3 使用分隔符清楚地指示输入的不同部分

使用分隔符,如三重引号XML 标签章节标题等,可以帮助区分文本的不同部分。

示例1:

GPT角色 角色内容
USER 用俳句来总结由三重引号分隔的文本。 “”“在此插入文本”“”

示例2:

GPT角色 角色内容
SYSTEM 您将获得一对关于同一主题的文章(用 XML 标记分隔)。先总结一下每篇文章的论点。然后指出他们中的哪一个提出了更好的论点并解释原因。
USER
在此插入第一篇文章
在此插入第二篇文章

示例3:

GPT角色 角色内容
SYSTEM 您将获得论文摘要和建议的标题。论文标题应该让读者清楚地了解论文的主题,但也应该引人注目。如果标题不符合这些标准,请提出 5 个替代方案。
USER 摘要:在此插入摘要 标题:在此插入标题

对于像这样的简单任务,使用分隔符可能不会影响输出质量。然而,任务越复杂,消除歧义就越重要。不要让 GPT 为了理解你所要求的内容而费力。

1.4 指定完成任务所需的步骤

对于某一些任务,最好提供一系列的步骤来提示模型。
也就是说,进行任务分解,将一个大的任务分成多个小的步骤来完成。
将这些步骤明确地写出来,可以帮助模型更好地理解和执行任务。

GPT角色 角色内容
SYSTEM 使用以下分步说明来响应用户输入。 步骤 1 - 用户将为您提供三引号中的文本。用一个句子总结这段文字,并加上前缀“摘要:”。 步骤 2 - 将步骤 1 中的摘要翻译成西班牙语,并添加前缀“翻译:”。
USER “”“在此插入文本”“”

1.5 提供小样本

提供适用于所有示例的“通用说明(general instructions)”,通常比"通过示例"演示"任务的所有排列"更有效,但在某些情况下,提供示例可能更容易。例如,如果您打算让模型复制"响应用户查询的特定风格",而这种风格又很难明确的进行描述。这种提供示例的方式被称为“少样本”提示。

GPT角色 角色内容
SYSTEM 以一致的风格回答。
USER 教我关于耐心的知识。
ASSISTANT 凿出最深山谷的河流,发源于一个不起眼的泉水;最伟大的交响乐源自一个音符;最复杂的挂毯都是从一根单独的线开始的。
USER 教我关于海洋的知识。

1.6 指定所需的输出长度

您可以要求模型生成给定目标长度的输出。目标输出长度可以根据单词、句子、段落、要点等的计数来指定。需要注意的是,指定生成特定数量的单词并不能保证高精度的结果。相比之下,该模型更可靠地生成具有特定数量的段落或要点的输出。

GPT角色 角色内容
USER 用大约 50 个单词概括由三引号分隔的文本。 “”“在此插入文本”“”
GPT角色 角色内容
USER 将由三个引号括起来的文本总结为两个段落。 “”“在此插入文本”“”
GPT角色 角色内容
USER 将由三引号分隔的文本总结为 3 个要点。 “”“在此插入文本”“”

2. 提供参考文本

GPT模型可以自信地编造虚假答案,尤其是在涉及深奥主题或引用和URL时。就像学生在考试时可以查看笔记来帮助自己更好地回答问题一样,向GPT模型提供参考文本可以帮助减少编造虚假答案的情况。

具体方法:

  • 提示模型使用参考文本来回答问题
  • 提示模型使用参考文本中的引用来回答问题

GPT模型可以自信地编造虚假答案,尤其是在涉及深奥主题或引用和URL时。就像学生在考试时可以查看笔记来帮助自己更好地回答问题一样,向GPT模型提供参考文本可以帮助减少编造虚假答案的情况。

具体方法:

  • 提示模型使用参考文本来回答问题
  • 提示模型使用参考文本中的引用来回答问题

2.1 提示模型使用参考文本来回答问题

如果我们可以为模型提供与当前查询相关的可靠信息,那么我们就可以要求模型使用提供的信息来进行回答。

GPT角色 角色内容
SYSTEM 使用三个引号内的文章来回答问题。如果答案在文章中找不到,请返回“我找不到答案”。
USER <插入文章,每篇文章用三个引号分隔> 问题:<在此插入问题>
示例

Prompt内容:

“”" 2022年的某一天,李明开着摩托车去给客户送货,路上遇到了一只小狗,他停下车去看了一下小狗,回去开车的时候货物不见了。李明在2023年进了一批货物,货物里面居然有一只小狗。“”"

问题:2022年李明开摩托车遇到了什么动物?

输出结果:

将引号内容中的2022年修改为2021年,再测试一下:

鉴于 GPT 的上下文窗口大小的有限,为了应用这个策略,我们(有时)需要某种方法来动态查找与所提出的问题相关的信息。而嵌入(Embeddings)就可用于实现高效的知识检索。有关如何实现这一点的更多详细信息,请参阅策略“使用基于嵌入的搜索来实现高效的知识检索” 。

2.2 提示模型使用参考文本中的引用来回答问题

如果输入的内容已经包含了相关知识,那么我们可以要求模型通过引用所提供文档中的段落来为其答案添加引文。需要注意的是,输出中的“引文”可以通过“在所提供文档中进行字符串匹配来进行程序验证”。

GPT角色 角色内容
SYSTEM 你将会得到一个由三个引号分隔的文档内容和一个问题。你的任务是只使用提供的文档内容来回答问题,并引用“用于回答问题的文档内容段落”。如果文档内容中没有包含用于回答该问题所需的信息,则简单地返回:“信息不足”。如果文档内容中提供了问题的答案,则必须使用“引文”进行注释。使用以下格式引用相关的段落。({“引文”: …})
USER “”“在此插入文档内容”“” 问题:<在此插入问题>
示例

英文效果:

中文效果:

Prompt内容:

“”"蒸汽机是一种以蒸汽为工作流体进行机械功的热力发动机。蒸汽机利用蒸汽压力产生的力推动活塞在气缸内来回移动。这种推力可以转化为:连杆和曲柄,转化为旋转力做功。术语“蒸汽机”通常仅适用于刚才描述的往复式发动机,而不适用于蒸汽轮机。蒸汽机是外燃机,其中工作流体与蒸汽分离 燃烧产物。用于分析此过程的理想热力循环称为朗肯循环。在一般用法中,术语“蒸汽机”可以指完整的蒸汽装置(包括锅炉等),例如铁路蒸汽机车和便携式发动机,或 可以单独指活塞或涡轮机,如梁式发动机和固定式蒸汽机。

尽管蒸汽驱动装置早在公元一世纪就为人所知,并且在 16 世纪也有一些其他用途的记录,但 Jerónimo de Ayanz y Beaumont 于 1606 年为他的第一台用于矿井排水的蒸汽驱动水泵的发明申请了专利 。托马斯·萨弗里 (Thomas Savery) 被认为是第一个商用蒸汽动力设备的发明者,该设备是一种直接在水面上使用蒸汽压力运行的蒸汽泵。托马斯·纽科门 (Thomas Newcomen) 于 1712 年开发出第一台商业成功的发动机,可以向机器传输连续动力。詹姆斯·瓦特 (James Watt) 在 1764 年做出了一项重大改进,将废蒸汽转移到一个单独的容器中进行冷凝,从而大大提高了每单位燃料消耗所获得的功量。到了 19 世纪,固定式蒸汽机为工业革命的工厂提供了动力。蒸汽机取代了明轮船上的船帆,蒸汽机车在铁路上运行。

直到 20 世纪初,往复活塞式蒸汽机一直是主要的动力来源,当时电动机和内燃机设计的进步导致商业用途中逐渐取代蒸汽机。由于成本更低、运行速度更高、效率更高,蒸汽轮机在发电中取代了往复式发动机。“”"

问题:第一台商业上成功的蒸汽机是什么?

在输出的结果中,通过增加引文内容,可以使得输出的结果更加可靠。同时可以验证答案的确是来源于原文的某一个段落,确保信息的真实性。

3. 将复杂的任务拆分为更简单的子任务

就像在软件工程中将复杂系统分解为一组模块化组件一样,在提交给GPT模型的任务中也是如此。复杂任务往往比简单任务出错率更高。此外,复杂任务通常可以重新定义为一系列简单任务的工作流程,其中前置任务的输出作为后续任务的输入。

具体方法:

  • 使用意图分类来识别与用户查询最相关的指令
  • 对于需要很长会话的对话应用,总结或过滤之前的对话
  • 分段总结长文档,并递归构建成完整摘要

3.1 使用意图分类来识别与用户查询最相关的指令

对于需要大量独立指令集来处理不同情况的任务,首先对查询类型进行分类并使用该分类来确定需要哪些指令可能会更好。这可以通过定义与处理给定类别中的任务相关的固定类别和硬编码指令来实现。该过程也可以递归地应用,将任务分解为一系列阶段。这种方法的优点是每个查询仅包含执行任务下一阶段所需的指令,与使用单个查询执行整个任务相比,这可以降低错误率。这还可以降低成本,因为更多的提示(large prompts)运行成本也会更高。(这段描述比较抽象,结合下面的例子来理解会清楚很多)

示例1

例如,对于一个客户服务查询系统,可以按照以下方式进行更好的查询分类。

SYSTEM Prompt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
我们将向您提供客户服务查询,并将每个查询分为一级分类和二级分类。请你以JSON格式回答问题,并且JSON包含以下字段:一级和二级。示例回答:{"一级":"一般查询","二级":"定价"}

一级分类:计费、技术支持、账户管理或一般查询。

计费二级分类:
- 取消订阅或升级
- 添加付款方式
- 收费说明
- 对收费提出异议

技术支持二级分类:
- 故障排除
- 设备兼容性
- 软件更新

账户管理二级分类:
- 密码重置
- 更新个人信息
- 关闭账户
- 账户安全

一般查询二级分类:
- 产品信息
- 定价
- 反馈
- 人工交流

我们提几个问题,进行客户服务查询:

针对我们提出的4个问题,GPT对意图的识别都是正确的,效果很棒。

这种实现思路,非常适合用来实现智能客服,以及指令类型的应用系统。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
USER
我需要让我的互联网再次工作起来。
ASSISTANT
{"一级":"技术支持","二级":"故障排除"}

USER
我忘记密码了
ASSISTANT
{"一级":"账户管理","二级":"密码重置"}

USER
我的软件兼容性有问题
ASSISTANT
{"一级":"技术支持","二级":"设备兼容性"}

USER
软件版本太旧了
ASSISTANT
{"一级":"技术支持","二级":"软件更新"}
示例2

根据客户查询的分类,可以向 GPT 模型提供一组更具体的指令来处理后续的步骤。例如,假设客户需要“故障排除”方面的帮助。

SYSTEM Prompt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
你将收到需要技术支持故障排查的客户服务咨询。请按照以下步骤帮助用户:

- 请他们检查所有进出路由器的电缆是否已连接。请注意,电缆随着时间的推移可能会变得松动,这是很常见的。
- 如果所有的电缆都已连接,但问题仍然存在,请询问他们使用的路由器型号是什么。
- 现在你将指导他们如何重启设备:
-- 如果型号是 MTD-327J,请建议他们按下红色按钮并保持5秒,然后等待5分钟后再测试连接的状态。
-- 如果型号是 MTD-327S,请建议他们拔下电源插头并重新插入,然后等待5分钟后再测试连接的状态。
- 如果客户在重启设备并等待5分钟后,问题仍然存在,请通过输出 {"IT support requested"} 将他们转接到IT支持服务。
- 如果用户开始提问与此话题无关的问题,那么请确认他们是否希望结束当前关于故障排除的聊天,并根据以下方案对他们的请求进行分类:


将客户的每个查询分为一级分类和二级分类。
请你以JSON格式回答问题,并且JSON包含以下字段:一级和二级。
示例回答:{"一级":"一般查询","二级":"定价"}

一级分类:计费、技术支持、账户管理或一般查询。

计费二级分类:
- 取消订阅或升级
- 添加付款方式
- 收费说明
- 对收费提出异议

技术支持二级分类:
- 故障排除
- 设备兼容性
- 软件更新

账户管理二级分类:
- 密码重置
- 更新个人信息
- 关闭账户
- 账户安全

一般查询二级分类:
- 产品信息
- 定价
- 反馈
- 人工交流

相比于第一个例子,本示例的Prompt要复杂许多,换做是人工都不一定能回答得很好,但是GPT的回复却非常的到位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
USER
我需要让我的互联网再次工作起来。
ASSISTANT
我明白你的困扰,让我们一步一步解决这个问题。

首先,你能检查一下连到路由器的电缆是否都已经连接好了吗? 这包括任何进入或离开路由器的电缆。时间长了,电缆可能会松动,这是很正常的。

USER
检查了,已经连接
ASSISTANT
好的,既然所有的电缆都已经连接好了,接下来我们需要了解一下你的路由器是什么型号。

USER
MTD-327S
ASSISTANT
好的,谢谢你提供了路由器的型号。对于MTD-327S这款路由器,我们需要做的是断电重启。

请你按照以下步骤操作:拔下电源插头,然后重新插入,然后等待5分钟后再测试网络连接的状态。

请先试一试,看看这样能不能解决你的问题。

USER
问题依然存在
ASSISTANT
{"IT support requested"}

USER
我忘记设备的密码了
ASSISTANT
{"一级":"账户管理","二级":"密码重置"}

3.2 对于需要很长会话的对话应用,总结或过滤之前的对话

由于 GPT 具有固定的上下文长度,因此用户和GPT之间的历史对话内容不能无限期地包含在上下文窗口中。

对于这个问题有多种解决方法,其中一种是对之前的对话进行总结。当输入内容的大小达到预定的阈值长度时,则触发对部分对话内容的总结,同时总结后的会话摘要可以作为系统提示信息的一部分。或者,可以在整个对话的过程中,在后台异步的总结之前的对话。

另一种解决方案,是动态的选择先前会话中与当前查询最相关的对话内容。这部分请参阅策略“使用基于嵌入的搜索实现高效的知识检索”。

举一个简单的例子:

1
2
3
4
5
6
7
8
9
例子1:客服聊天机器人
假设一个客服聊天机器人正在与用户讨论复杂的技术问题。
对话很长,涉及多个问题和解决方案。当对话字符达到2000时,系统触发一个机制将前1000个字符的内容总结为200字符的摘要。
这样,新的问题和回答可以继续添加到对话中,而先前对话的重要部分仍然作为摘要保留,可以作为后续对话的参考。

例子2:法律咨询机器人
假设一个法律咨询机器人正在与用户讨论不同的法律问题,涉及合同、知识产权和劳动法等多个主题。
当用户提出一个特定的关于劳动法的问题时,系统可以动态选择先前关于劳动法的对话部分,忽略与合同和知识产权相关的内容。
这样,一方面不会超过上下文的最大长度,同时可以更精确地响应当前的问题,而不被不相关的信息所干扰。

3.3 分段总结长文档,并递归构建成完整摘要

由于 GPT 具有固定的上下文长度,因此它不能用于在单次查询中总结长度超过“固定上下文长度减去生成内容的长度”的文本。

要总结一个很长的文档(例如一本书),我们可以使用一系列的查询来总结文档的每个部分。通过将每一个章节的摘要合并在一起并进行总结,可以进一步生成摘要的摘要。这个处理过程可以递归地进行,直到对整个文档完成总结。如果有必要使用前面章节的信息来理解后面的章节,那么另一个有用的技巧是,在总结书中任何给定部分的内容时,都将前面章节得到的摘要(a running summary,持续摘要)包含进来。OpenAI 在之前的研究中,已经使用了 GPT-3 的变体研究了这种总结书籍的过程的有效性。

举一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
假设一本书籍有三章:

第一章是关于一个男孩的生活。
第二章描述了他的大学生涯。
第三章讲述了他的工作生涯。

如果我们对每章进行摘要:
第一章摘要:男孩在乡村长大。
第二章摘要:男孩在城市的大学学习。
第三章摘要:男孩成为了一名医生。

如果我们用“持续摘要”的方法:
第一章的持续摘要:男孩在乡村长大。
到第二章时的持续摘要:男孩在乡村长大,后来去城市的大学学习。
到第三章时的持续摘要:男孩在乡村长大,后来去城市的大学学习,并最终成为了一名医生。

通过这种持续摘要的方式,提供了一个连续的、不断更新的上下文信息,当后续的章节与前面的章节有紧密的联系时,可以更好的理解最新的章节。

4. 给 GPT 时间“思考”

如果让你计算17乘以28,你可能不会立即知道答案,但是可以花时间算出来。类似地,当GPT试图立即回答问题时,它会犯更多的推理错误,而不是花时间计算出答案。在回答之前,要求给出一系列的推理过程可以帮助GPT更可靠地推理正确的答案。

具体方法:

  • 提示模型不要匆忙得出结论,而是要先找出自己的解决方案
  • 使用内心独白或一系列问题来隐藏模型的推理过程
  • 询问模型在之前的处理过程中是否遗漏了什么内容

4.1 提示模型不要匆忙得出结论,而是要先找出自己的解决方案

有时候,当我们明确指示模型在得出结论之前从基本原理出发进行推理,我们可以得到更好的结果。例如,假设我们需要一个模型来评估学生对数学问题的解决方案,最明显的解决方法就是简单地询问模型“学生的解决方案”是否正确。

SYSTEM Prompt

1
确定学生的解决方案是否正确。

USER Prompt

1
2
3
4
5
6
7
8
9
10
11
12
问题描述:我正在建设一个太阳能发电设施,并且我需要帮助以解决财务问题。

- 土地每平方英尺价格为$100
- 我可以以每平方英尺$250的价格购买太阳能板
- 我谈判了一份维护合同,第一年将花费我固定的$100,000,以及额外的每平方英尺$10
第一年运营的总成本作为平方英尺数量的函数是多少?

学生的解决方案:设x为安装面积(以平方英尺为单位)。
1.土地成本:100x
2.太阳能板成本:250x
3.维护成本:100,000 + 10x
总成本:100x + 250x + 100,000 + 10x = 450x + 100,000

输出的结果是,学生的解决方案是正确的。

但是学生的解决方案实际上是不正确的!我们可以通过提示模型首先生成自己的解决方案来让模型注意到这一点。

SYSTEM Prompt

1
2
3
首先,针对这个问题,请先思考并找出你自己的解决方案,列出计算过程。
将你的解决方案的函数与学生的解决方案的函数分别列出来,再将函数进行比较,评估学生的解决方案是否正确。
请在你自己完成问题的解决方案之后,再判断学生的解决方案是否正确。

这次得出了正确的结论,学生的答案是错误的。

4.2 使用内心独白或一系列查询来隐藏模型的推理过程

前面的策略表明,在回答特定问题之前,模型有时需要详细地推理问题。对于某些应用来说,模型用于得出最终答案的推理过程是不适合与用户分享的。例如,在辅导应用中,我们可能希望鼓励学生自己解决问题,但模型对学生解决方案的推理过程可能会泄露答案给学生。

内心独白是一种可以用来缓解这个问题的策略。内心独白的思路是指导模型将那些“不应被用户看到的输出部分”放入一种结构化的格式中,以便于解析。然后,在将输出呈现给用户之前,对输出进行解析,并且只显示输出的一部分。

SYSTEM Prompt

1
2
3
4
5
6
7
8
9
按照以下步骤回答用户的问题。

步骤1 - 首先自己解决问题。不要依赖学生的解决方案,因为它可能是错误的。将所有此步骤的工作用三个引号(""")括起来。

步骤2 - 将你的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。将所有此步骤的工作用三个引号(""")括起来。

步骤3 - 如果学生犯了错误,确定你可以给学生什么提示而不泄露答案。将所有此步骤的工作用三个引号(""")括起来。

步骤4 - 如果学生犯了错误,提供上一步中的提示给学生(不用三个引号括起来)。与其写“步骤4 - ...”,不如写“提示:”。

USER Prompt

1
2
3
问题陈述:一个盒子里有4个红球和6个蓝球。从盒子中不放回地抽出两个球。抽出的两个球中有一个是红色和另一个是蓝色的概率是多少?

学生解决方案:(4/10)*(6/9) = 24/90 = 4/15

如果使用GPT 3.5,回答的结果不太稳定,效果不好。

因此,下面使用GPT 4来测试。由于我的账号没有GPT 4的API权限,所以将SYSTEM和USER的提示合并后,放到ChatGPT Plus网页版中的GPT 4来测试。

前三个步骤,模型按照要求解答,并以三个引号括了起来。

最后一部分,是在判断了学生的答案有误之后,用于展示给学生的解题提示。

在实际的应用开发中,对于GPT的回复,可以通过指定的格式(三个引号)将前三个步骤的结果过滤掉,只返回最后一步的提示内容展示给学生。

4.3 使用一系列的查询来实现

或者,这可以通过一系列查询来实现,其中除了最后一个查询之外,所有查询的输出都对最终用户隐藏。

首先,我们可以让模型来解决问题。由于这个初始查询不需要使用学生的解决方案,因此可以省略。这样做还有一个额外的优点,即模型的解决方案不会因“学生尝试的解决方案”而产生偏差。

USER Prompt

1
已知一个盒子里有4个红色的球和6个蓝色的球。现在从这个盒子里抽出两个球,并且抽出后不放回盒子中。请问,抽出的两个球中有一个是红色而另一个是蓝色的概率是多少?请一步步思考

接下来,我们可以让模型使用所有可用的信息来评估学生解决方案的正确性。

SYSTEM Prompt

1
将你的解决方案与学生的解决方案进行比较,评估学生的解决方案是否正确。

USER Prompt

1
2
3
4
5
6
7
8
9
10
11
12

问题陈述:"""一个盒子里有4个红色的球和6个蓝色的球。从盒子里抽出两个球,不放回。抽出的两个球中有一个是红色而另一个是蓝色的概率是多少?"""

你的解决方案:"""有两种可能的成功结果:要么我们先抽一个红色球然后是一个蓝色球,要么我们先抽一个蓝色球然后是一个红色球。我们将找出这些结果各自的概率,然后将它们加在一起。

1)先红后蓝:第一个抽到红色球的概率是4/10,因为总共有10个球中有4个是红色的。抽了一个红色球后,剩下3个红球和6个蓝球,所以下一个抽到蓝色球的概率是6/9。所以,这种结果的概率是(4/10)*(6/9)。

2)先蓝后红:第一个抽到蓝色球的概率是6/10,因为总共有10个球中有6个是蓝色的。抽了一个蓝色球后,剩下4个红球和5个蓝球,所以下一个抽到红色球的概率是4/9。所以,这种结果的概率是(6/10)*(4/9)。

现在我们把这两种结果的概率加在一起:(4/10)(6/9)+(6/10)(4/9)= 24/90 + 24/90 = 48/90。这个分数简化为8/15,所以抽出一个红球和一个蓝球的概率是8/15。"""

学生的解决方案:"""(4/10)*(6/9)= 24/90 = 4/15"""

最后,我们可以让模型使用自己的分析来以乐于助人的导师的角色构建回复。

SYSTEM Prompt

1
你是一名数学导师。如果学生犯了错误,请以不透露答案的方式向学生提供提示。如果学生没有犯错,只需给他们一个鼓励性的评论。

USER Prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
问题陈述:"""一个盒子里有4个红色的球和6个蓝色的球。从盒子里抽出两个球,不放回。抽出的两个球中有一个是红色而另一个是蓝色的概率是多少?"""

你的解决方案:"""有两种可能的成功结果:要么我们先抽一个红色球然后是一个蓝色球,要么我们先抽一个蓝色球然后是一个红色球。我们将找出这些结果各自的概率,然后将它们加在一起。

1)先红后蓝:第一个抽到红色球的概率是4/10,因为总共有10个球中有4个是红色的。抽了一个红色球后,剩下3个红球和6个蓝球,所以下一个抽到蓝色球的概率是6/9。所以,这种结果的概率是(4/10)*(6/9)。

2)先蓝后红:第一个抽到蓝色球的概率是6/10,因为总共有10个球中有6个是蓝色的。抽了一个蓝色球后,剩下4个红球和5个蓝球,所以下一个抽到红色球的概率是4/9。所以,这种结果的概率是(6/10)*(4/9)。

现在我们把这两种结果的概率加在一起:(4/10)(6/9)+(6/10)(4/9)= 24/90 + 24/90 = 48/90。这个分数简化为8/15,所以抽出一个红球和一个蓝球的概率是8/15。"""

学生的解决方案:"""(4/10)*(6/9)= 24/90 = 4/15"""

分析:"""学生的解决方案是错误的。他们只考虑了先抽一个红色球然后抽一个蓝色球的情况,而忽略了先抽一个蓝色球然后抽一个红色球的情况。正确的解决方案是将这两种情况的概率相加,即8/15。"""

使用这种方法,一次只让模型解决一个问题。同时,将前一个步骤得到的内容,合并到最新的查询Prompt中,这样得到的效果确定性更强。这其实就是逐步引导GPT去思考问题的过程,而每一个问题都会更加明确、简单,因此效果会比较稳定。

4.5 询问模型在之前的处理过程中是否遗漏了什么内容

假设我们正在使用一个模型来列出与特定问题相关的信息源摘录。在列出每个摘录后,模型需要确定是否应该开始写另一个摘录,还是应该停止。如果源文件很大,模型很容易过早停止,无法列出所有相关摘录。在这种情况下,通常可以通过提示模型进行后续查询来找到之前遗漏的摘录,从而获得更好的性能。

SYSTEM Prompt

1
2
3
4
5
6
7
你将会收到一个由三个引号包含的文档。你的任务是选出与以下问题有关的摘录:"人工智能历史中有哪些重要的范式转变。"

确保摘录包含解释它们所需的所有相关上下文 - 换句话说,不要提取缺少重要上下文的小片段。请按照以下的JSON格式提供输出:

[{"excerpt": "在这里插入摘录"},
...
{"excerpt": "在这里插入摘录"}]

USER Prompt

1
"""<insert document here>"""

ASSISTANT Result

1
2
3
[{"excerpt": "the model writes an excerpt here"},
...
{"excerpt": "the model writes another excerpt here"}]

USER Prompt

1
Are there more relevant excerpts? Take care not to repeat excerpts. Also ensure that excerpts contain all relevant context needed to interpret them - in other words don't extract small snippets that are missing important context.

5. 使用外部工具

通过使用其他工具的输出来弥补GPT的不足。例如,使用文本检索系统来告诉GPT相关文档的信息,或者使用代码执行引擎来帮助GPT进行数学计算和代码运行。如果有其他工具可以更可靠或更有效地完成某个任务,就应该使用这些工具,以获得最佳效果。

具体方法:

  • 使用基于嵌入的搜索实现高效的知识检索
  • 通过代码执行来进行更准确的计算或调用外部API
  • 为模型提供访问特定函数的权限

5.1 使用基于嵌入的搜索来实现高效的知识检索

如果作为输入的一部分提供,模型可以利用外部信息源。这可以帮助模型生成更明智和最新的响应。例如,如果用户询问有关特定电影的问题,将有关电影的高质量信息(例如演员、导演等)添加到模型的输入中可能会很有用。嵌入可用于实现高效的知识检索,以便在运行时将相关信息动态添加到模型输入中。

文本嵌入是一个向量,可以衡量文本字符串之间的相关性。相似或相关的字符串将比不相关的字符串靠得更近。这一事实以及快速向量搜索算法的存在意味着嵌入可用于实现高效的知识检索。特别是,一个文本语料库可以被分割成块,每个块都可以被嵌入和存储。然后可以嵌入给定的查询并执行向量搜索以从语料库中找到与查询最相关的嵌入文本块(即在嵌入空间中最接近)。

比如ChatGLM+LangChain就是一种开源的领域大模型解决方案,具体可以参考相关资料。

5.2 使用代码执行来执行更准确的计算或调用外部 API

不能依赖 GPT 自行准确地执行算术或长计算。在需要的情况下,可以指示模型编写和运行代码,而不是进行自己的计算。特别是,可以指示模型将要运行的代码放入指定的格式中,例如三重 backtics。生成输出后,可以提取并运行代码。最后,如果有必要,可以将代码执行引擎(即 Python 解释器)的输出作为输入提供给下一个查询的模型。

示例:

SYSTEM Prompt

1
您可以通过将 Python 代码括在三重反引号中来编写和执行 Python 代码,例如代码在这里。使用它来执行计算。

USER Prompt

1
找出以下多项式的所有实值根:3x**5 - 5x4 - 3\*x3 - 7\*x - 10。

ASSISTANT Result

1
2
3
4
为了找出多项式的所有实根,我们可以使用 Python 的 numpy 库中的 roots 函数。这个函数将计算出一个多项式的所有根(包括实根和复根)。为了只获取实根,我们可以过滤出那些虚部为零的根。

*以下是对应的 Python 代码:*

运行这段代码将会给出多项式 3x55x43x37x103x5 - 5x4 - 3x^3 - 7x - 10 的所有实根。

6. 系统地测试变化

有时很难判断更改(例如,新指令或新设计)是否会使您的系统变得更好或更糟。查看几个示例可能会暗示哪个更好,但是样本量较小时,很难区分真正的改进还是随机的运气。也许这种变化有助于某些输入的性能,但会损害其他输入的性能。

评估程序(或“evals”)对于优化系统设计很有用。好的评价是:

  • 代表现实世界的使用(或至少是多样化的)

  • 包含许多测试用例以获得更大的统计能力(有关指南,请参见下表)

  • 易于自动化或重复

DIFFERENCE TO DETECT SAMPLE SIZE NEEDED FOR 95% CONFIDENCE
30% ~10
10% ~100
3% ~1,000
1% ~10,000

对输出结果的评估可以由计算机、人工或混合方式完成。计算机可以根据客观标准(例如只有一个正确答案的问题)以及一些主观或模糊标准自动进行评估,其中模型输出由其他模型查询进行评估。OpenAI Evals 是一个开源软件框架,提供创建自动 evals 的工具。

当存在一系列被认为质量同样高的可能输出时(例如对于答案较长的问题),基于模型的评估就很有用。哪些内容可以通过基于模型的评估进行实际评估,哪些内容需要人工评估,这两者之间的界限是模糊的,并且随着模型能力的提高而不断变化。我们鼓励通过实验来了解基于模型的评估在您的使用案例中的效果如何。

6.1 参考黄金标准答案评估模型输出

假设已知问题的正确答案应该参考一组特定的已知事实。然后我们可以使用模型查询来计算答案中包含了多少所需事实。

示例1:

SYSTEM Prompt

1
2
3
4
5
6
7
8
9
10
11
12
13
您将获得由三重引号分隔的文本,这些文本应该是问题的答案。检查答案中是否直接包含以下信息:

- 尼尔阿姆斯特朗是第一个在月球上行走的人。
- 尼尔·阿姆斯特朗首次踏上月球的日期是 1969 年 7 月 21 日。

对于这些点中的每一个,执行以下步骤:

1- 重申这一点。
2- 引用最接近这一点的答案。
3- 考虑阅读引文但不了解主题的人是否可以直接推断出这一点。在下定决心之前解释为什么或为什么不。
4- 如果对 3 的回答是“是”,则写“是”,否则写“否”。

最后,提供有多少个“是”答案的计数。将此计数提供为 {"count":**}。

USER Prompt

1
"""尼尔阿姆斯特朗因成为第一个踏上月球的人类而闻名。这一历史性事件发生在 1969 年 7 月 21 日,阿波罗 11 号任务期间。"""

ASSISTANT Result

1
2
3
4
5
6
7
1 - 尼尔阿姆斯特朗是第一个在月球上行走的人。答案中的引文:"尼尔阿姆斯特朗因成为第一个踏上月球的人类而闻名。"考虑引文,尽管它没有直接说阿姆斯特朗是第一个在月球上行走的人,但它明确说阿姆斯特朗是第一个踏上月球的人,这也暗示了他是第一个在月球上行走的人。所以,一个人可以从这个引文中直接推断出阿姆斯特朗是第一个在月球上行走的人。答案:是

2 - 尼尔·阿姆斯特朗首次踏上月球的日期是 1969 年 7 月 21 日。答案中的引文:"这一历史性事件发生在 1969 年 7 月 21 日,阿波罗 11 号任务期间。"考虑引文,它明**确地提到了这一历史性事件(即阿姆斯特朗踏上月球)发生在 1969 年 7 月 21 日。因此,一个人可以从这个引文中直接推断出尼尔·阿姆斯特朗首次踏上月球的日期是 1969 年 7 月 21 日。答案:是

{"count": 2}

这种基于模型的评估有很多可能的变体。考虑以下变体,它跟踪候选答案和黄金标准答案之间的重叠类型,并跟踪候选答案是否与黄金标准答案的任何部分相矛盾。

示例2:

SYSTEM Prompt

1
2
3
4
5
6
7
使用以下步骤响应用户输入。在继续之前完全重述每个步骤。即“第 1 步:原因……”。

第 1 步:逐步推理提交的答案中的信息与专家答案相比是否是:不相交、相等、子集、超集或重叠(即一些交集但不是子集/超集)。

第 2 步:逐步推理提交的答案是否与专家答案的任何方面相矛盾。

第 3 步:输出结构如下的 JSON 对象:{"type_of_overlap": "disjoint" or "equal" or "subset" or "superset" or "overlapping", "contradiction": true or false}

USER Prompt

1
2
3
4
5
问题:“”“Neil Armstrong 最著名的事件是什么?它发生在什么日期?假定 UTC 时间。”””

提交的答案:“”“他不是在月球上行走吗?”“”

专家解答:“”“尼尔阿姆斯特朗最著名的是第一个登上月球的人。这一历史性事件发生在 1969 年 7 月 21 日。”“”

ASSISTANT Result

1
2
3
4
5
6
7
8
9
10
11
第 1 步:逐步推理提交的答案中的信息与专家答案相比是什么关系?

提交的答案"他不是在月球上行走吗?"只包含了专家答案的一部分信息,也就是尼尔·阿姆斯特朗在月球上行走的事实。但是,它没有提供具体的日期,也没有明确表述尼尔·阿姆斯特朗是第一个登上月球的人。所以,提交的答案是专家答案的子集。

第 2 步:逐步推理提交的答案是否与专家答案的任何方面相矛盾?

提交的答案没有与专家答案产生任何矛盾,它只是没有提供所有的信息。

第 3 步:输出结构如下的 JSON 对象:

{"type_of_overlap": "subset", "contradiction": false}

要编写优质的prompt,从日常实践来看,用下述结构,并且提出非常具体的要求,则基本可以让LLM输出你想要的结果

✅ 角色、技能、个性
✅ 目标
✅ 具体的上下文、关键词、负面词
✅ 输入规则
✅ 输出规则
✅ 输入输出的例子

附图是两个优秀的Prompt:AutoGPT核心指令+小红书写手。都覆盖了框架的大部分

1️⃣ 角色、技能、个性
角色:该提示以声明AI的明确角色开始。这已经成为了标准的最佳实践。它会切换到那个角色来思考问题
技能:要告诉它能做什么事情,有哪些工具可以用
个性:输出的语调、个性(尤其是需要生成内容)、沟通方式等

2️⃣ 目标
告知让它完成一个什么目标。这是最核心的,必须非常清晰明确

3️⃣ 具体的上下文、关键词、负面词
上下文:这个尤其重要,要告知它已经发生了什么,有哪些具体信息。它才可以给出独特的结果

关键词列表:尽量的告诉它具体的关键词,尤其是对生成内容的时候,要有个性化的文案和创意,这是不可缺少的

负面词:让它避免输出不需要的内容。包括不要输出什么样的内容

4️⃣ 输入规则
明确输入的格式,有的时候最好用JSON格式给到它,这样就不会有歧义

5️⃣ 输出规则
这个非常重要,越详细越好。比如说明确格式,要JSON或者MD格式,要Bullet points,要长度,要表格,要emoji等。

比如说要确认要哪种内容,要忽略哪些 。

要遵循哪些策略等等

6️⃣ 输入输出的例子

在上面的输入输出规则基础上,最好的情况是给出一到多个例子。LLM在模仿例子方面非常的杰出,基本上给了3个典型的例子,后面类似的情况一定会严格按照例子来。

参考

  1. AI技术前沿
  2. Prompt 提示工程指南
  3. Prompt 编写模式
  4. Awesome ChatGPT Prompts